package com.snpic.appaw.module.insure.service.orc;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.snpic.appaw.framework.common.exception.ErrorCode;
import com.snpic.appaw.framework.common.pojo.CommonResult;
import com.snpic.appaw.module.insure.config.S3Config;
import com.snpic.appaw.module.insure.controller.app.orc.vo.*;
import com.snpic.appaw.module.insure.dal.dataobject.cxProvince.CxProvinceDO;
import com.snpic.appaw.module.insure.dal.mysql.cxProvince.CxProvinceMapper;
import com.snpic.appaw.module.insure.enums.InsureConstant;
import com.snpic.appaw.module.insure.service.s3.AmazonS3ObjectService;
import com.snpic.appaw.module.insure.util.s3.FileUtil;
import com.snpic.appaw.module.third.api.bjpt.BJPTApi;
import com.snpic.appaw.module.third.api.bjpt.dto.*;
import com.snpic.appaw.module.third.api.bjpt.dto.iSPolicyQuery.ISMotorDTO;
import com.snpic.appaw.module.third.api.bjpt.dto.iSPolicyQuery.ISPolicyQueryDetailResDTO;
import com.snpic.appaw.module.third.api.bjpt.dto.iSPolicyQuery.ISPolicyQueryMainRequest;
import com.snpic.appaw.module.third.api.bjpt.dto.iSPolicyQuery.ISRelatedPartyDTO;
import com.snpic.appaw.module.third.api.deepOCR.DeepOCRApi;
import com.snpic.appaw.module.third.api.deepOCR.dto.IdCardReqDTO;
import com.snpic.appaw.module.third.api.deepOCR.dto.IdCardRespDTO;
import com.snpic.appaw.module.third.api.deepOCR.dto.VehicleLicenseReqDTO;
import com.snpic.appaw.module.third.api.deepOCR.dto.VehicleLicenseRespDTO;
import com.snpic.appaw.module.third.enums.ThirdConstant;
import jakarta.annotation.Nullable;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.bean.BeanUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Base64;
import java.util.List;

import static com.snpic.appaw.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.snpic.appaw.module.insure.enums.ErrorCodeConstants.*;
import static com.snpic.appaw.module.insure.enums.InsureConstant.*;

/**
 * @author JiJun
 * @date 2025/9/11 11:27
 * @修改时间 2025/9/11 11:27
 * @description 使用易道博识ORC接口 和 报价平台接口 的服务
 */
@Service
@Slf4j
public class ClientOCRServiceImpl implements ClientOCRService {
	@Resource
	private DeepOCRApi deepOCRApi;

	@Resource
	private BJPTApi bjptApi;

	@Resource
	private CxProvinceMapper cxProvinceMapper;

	@Resource
	private AmazonS3ObjectService amazonS3ObjectService;

	@Resource
	private FileUtil fileUtil;

	@Resource
	private S3Config s3Config;


	/**
	 * 行驶证(正页识别)
	 *
	 * @param reqVO
	 * @return
	 */
	@Override
	public VehicleLicenseRespVO vehicleLicense(@Valid VehicleLicenseReqVO reqVO) {
		//1. ORC识别行驶证(正页识别),通用方法
		Result_VehicleLicense resultVehicleLicense = getOcrResult_vehicleLicense(reqVO);
		//2.5 校验车主姓名
		if (!reqVO.getCarOwer().equals(resultVehicleLicense.owner())) {
			//当前车主姓名与上传行驶证信息不一致，请核对后重新填写或上传
			log.error("当前车主姓名与上传行驶证信息不一致，请核对后重新填写或上传,reqVO={},ORC识别结果中的车主姓名={}", reqVO, resultVehicleLicense.owner());
			throw exception(OWNER_NAME_VERIFICATION_FAILED);
		}
		//2.6 校验车牌号
		if (!reqVO.getLicensePlateNumber().equals(resultVehicleLicense.plateNo())) {
			//请上传沪XXXX的行驶证
			log.error("当前车牌号与上传行驶证信息不一致，请核对后重新填写或上传,reqVO={},ORC识别结果中的车牌号={}", reqVO, resultVehicleLicense.plateNo());
			throw exception(new ErrorCode(6_0111, "上传" + reqVO.getLicensePlateNumber() + "的行驶证"));
		}


		//3. 请求第三方接口,报价平台-历史保单查询
		//3.1根据车牌号前缀plateNo_prefix去查询得到机构号和操作员工号(虚拟员工)
		CxProvinceDO cxProvinceDO = getCxProvinceDO(resultVehicleLicense.plateNo());
		//只有存在"证件号码"才能进行这步验证，
		boolean overwrittenByQueryHisPolicy = false;
		if (StrUtil.isNotEmpty(reqVO.getIdNo())) {
			//3.2 开始调用，报价平台，历史保单查询
			ISPolicyQueryDetailResDTO isPolicyQueryDetailResDTO = invokeQueryHisPolicyDetail(cxProvinceDO.getIssueCompany(), cxProvinceDO.getSalesmanCode(), resultVehicleLicense.plateNo(),resultVehicleLicense.vin());
			//3.3 进行逻辑判断,覆写OCR结果
			if (isPolicyQueryDetailResDTO != null) {
				overwrittenByQueryHisPolicy = processHisPolicyDetail(isPolicyQueryDetailResDTO, resultVehicleLicense.vin(), reqVO.getIdNo(), resultVehicleLicense.respVO());
			}
		}

		/*改为前端调用车辆车型查询接口
		//4. 把ORC识别的结果中的车架号，调用报价平台的车辆车型查询接口，校验车辆信息是否正确
		if (!overwrittenByQueryHisPolicy) {  //如果3中已经覆写，就不要进行这部分操作了
			//4.1 创建请求接口用的入参carModelInfoInquiryReqTotalDto
			CarModelInfoInquiryReqTotalDto carModelInfoInquiryReqTotalDto = new CarModelInfoInquiryReqTotalDto();
			//4.1.1 补充请求头
			CxRequestHeadDto cxRequestHeadDto = new CxRequestHeadDto();
			carModelInfoInquiryReqTotalDto.setRequestHead(cxRequestHeadDto);
			cxRequestHeadDto.setClientSeqNo(UUID.randomUUID().toString());  //UUID
			//补充机构号
			cxRequestHeadDto.setComCode(cxProvinceDO.getIssueCompany());
			//补充操作员工号
			cxRequestHeadDto.setUserCode(cxProvinceDO.getSalesmanCode());
			//4.1.2 补充请求体
			CarModelInfoInquiryReqDto carModelInfoInquiryReqDto = new CarModelInfoInquiryReqDto();
			carModelInfoInquiryReqTotalDto.setRequestBody(carModelInfoInquiryReqDto);
			//根据车架号查询车型，使用请求类型=1
			carModelInfoInquiryReqDto.setInquiryType(SystemConstant.StrOne);
			carModelInfoInquiryReqDto.setCompanyCode(cxRequestHeadDto.getComCode());
//		carModelInfoInquiryReqDto.setLicenseNo(plateNo);  可以不传车牌号码
//		carModelInfoInquiryReqDto.setVin(vin);  //TODO 记得还原
			carModelInfoInquiryReqDto.setVin("LYT3462D2GMLC8031");  //测试用固定VIN
			//4.2 调用第三方接口
			CommonResult<CarModelInfoInquiryRespTotalDto> carModelInfoInquiryRespTotalDtoCommonResult = null;

			try {
				carModelInfoInquiryRespTotalDtoCommonResult = bjptApi.carModelInfoInquiry(carModelInfoInquiryReqTotalDto);
			} catch (Exception e) {
				log.error("bjptApi调用失败", e);
				throw exception(THIRD_PARTY_INTERFACE_CALL_FAILED);
			}
			if (carModelInfoInquiryRespTotalDtoCommonResult == null
				|| carModelInfoInquiryRespTotalDtoCommonResult.getCode() != 0
				|| carModelInfoInquiryRespTotalDtoCommonResult.getData() == null
				|| !ThirdConstant.BJPT_SUCCESS_FLAG.equals(carModelInfoInquiryRespTotalDtoCommonResult.getData().getResponseHead().getResult())
			) {
				log.error("调用报价平台的车辆车型查询接口失败,carModelInfoInquiryRespTotalDtoCommonResult={}", carModelInfoInquiryRespTotalDtoCommonResult);
				throw exception(THIRD_PARTY_INTERFACE_CALL_FAILED);
			}

			//4.3 carModelInfoInquiryRespDto中获取到的车型填入respVO
			CarModelInfoInquiryRespDto carModelInfoInquiryRespDto = carModelInfoInquiryRespTotalDtoCommonResult.getData().getResponseBody();
			if (CollUtil.isEmpty(carModelInfoInquiryRespDto.getCarModelList()) || StrUtil.isBlank(carModelInfoInquiryRespDto.getCarModelList().get(0).getModelcname())) {
				log.warn("调用报价平台的车辆车型查询接口,返回的车型简体中文名称(品牌型号)为空");
				//若从OCR识别获取的车辆信息，则不回显品牌型号
				respVO.getResult().getModel().setWords(null);
//				throw exception(BJPT_MODEL_NOT_EXIST);
			}
			//4.5 当报价平台车辆查询接口返回“验证码”
					//校验码（江苏）,一个图片
			String checkAnswer = carModelInfoInquiryRespDto.getCheckAnswer();
			//查询码（江苏）
			String pmQueryNo = carModelInfoInquiryRespDto.getPmQueryNo();
			if(StrUtil.isNotEmpty(checkAnswer) && StrUtil.isNotEmpty(pmQueryNo)){
				//报价平台车辆查询接口返回“验证码”
				respVO.setPmQueryNo(pmQueryNo).setCheckAnswer(checkAnswer);
			}

			//4.4 覆写
			respVO.getResult().getModel().setWords(carModelInfoInquiryRespDto.getCarModelList().get(0).getModelcname());
		}
		 */

		return resultVehicleLicense.respVO();
	}

	/**
	 * 取得ORC结果,行驶证正面,并校验
	 *
	 * @param reqVO
	 * @return
	 */
	@NotNull
	private Result_VehicleLicense getOcrResult_vehicleLicense(VehicleLicenseReqVO reqVO) {
		//1. ORC识别驾驶证正面
		VehicleLicenseReqDTO reqDTO = BeanUtil.copyProperties(reqVO, VehicleLicenseReqDTO.class);
		CommonResult<VehicleLicenseRespDTO> vehicleLicenseRespDTOCommonResult = null;
		try {
			vehicleLicenseRespDTOCommonResult = deepOCRApi.vehicleLicense(reqDTO);
		} catch (Exception e) {
			log.error("deepOCRApi调用失败", e);
			throw exception(THIRD_PARTY_INTERFACE_CALL_FAILED);
		}
		if (vehicleLicenseRespDTOCommonResult == null
			|| vehicleLicenseRespDTOCommonResult.getCode() != 0
			|| vehicleLicenseRespDTOCommonResult.getData() == null
			|| vehicleLicenseRespDTOCommonResult.getData().getError_code() != 0) {
			log.error("行驶证(正页识别)失败,vehicleLicenseRespDTOCommonResult={}", vehicleLicenseRespDTOCommonResult);
			throw exception(VEHICLE_LICENSE_FAILURE);
		}

		//2. 车牌号和车主姓名校验
		//2.1 ORC识别结果中的车牌号和车架号必然存在
		VehicleLicenseRespDTO vehicleLicenseRespDTO = vehicleLicenseRespDTOCommonResult.getData();
		//提前准备一个返回值respVO
		VehicleLicenseRespVO respVO = BeanUtil.toBean(vehicleLicenseRespDTO, VehicleLicenseRespVO.class);
		//OCR识别得到的品牌型号始终不是我需要的，所以这里手动设置respVO里的品牌型号为null
		respVO.getResult().getModel().setWords(null);
		//2.2 行驶证中识别到的车牌
		String plateNo = vehicleLicenseRespDTO.getResult().getPlateno().getWords();
		if (StrUtil.isEmpty(plateNo)) {
			log.error("行驶证(正页识别)失败,ORC识别结果中的车牌号不存在,vehicleLicenseRespDTO.getResult()={}", vehicleLicenseRespDTO.getResult());
			throw exception(VEHICLE_LICENSE_FAILURE);
		}
		//2.3 行驶证中识别到的车架号vin
		String vin = vehicleLicenseRespDTO.getResult().getVin().getWords();
		if (StrUtil.isEmpty(vin)) {
			log.error("行驶证(正页识别)失败,ORC识别结果中的车架号不存在,vehicleLicenseRespDTO.getResult()={}", vehicleLicenseRespDTO.getResult());
			throw exception(VEHICLE_LICENSE_FAILURE);
		}
		//2.4 行驶证中识别到的车主姓名
		String owner = vehicleLicenseRespDTO.getResult().getOwner().getWords();
		if (StrUtil.isEmpty(owner)) {
			log.error("行驶证(正页识别)失败,ORC识别结果中的车主姓名不存在,vehicleLicenseRespDTO.getResult()={}", vehicleLicenseRespDTO.getResult());
			throw exception(VEHICLE_LICENSE_FAILURE);
		}
		return new Result_VehicleLicense(respVO, plateNo, vin, owner);
	}

	/**
	 * 取得ORC结果,身份证,并校验
	 *
	 * @param reqVO
	 * @return
	 */
	private Result_IDCard getOcrResult_idCard(IdCardReqVO reqVO) {
		//1. OCR识别身份证正面
		IdCardReqDTO idCardReqDTO = BeanUtil.toBean(reqVO, IdCardReqDTO.class);
		CommonResult<IdCardRespDTO> idCardRespDTOCommonResult = null;
		try {
			idCardRespDTOCommonResult = deepOCRApi.idCard(idCardReqDTO);
		} catch (Exception e) {
			log.error("deepOCRApi调用失败", e);
			throw exception(THIRD_PARTY_INTERFACE_CALL_FAILED);
		}
		IdCardRespDTO respDTO = idCardRespDTOCommonResult.getData();
		if (idCardRespDTOCommonResult.getCode() != 0 || respDTO == null || respDTO.getError_code() != 0
		) {
			log.error("身份证结构化识别V1失败,idCardRespDTOCommonResult={}", idCardRespDTOCommonResult);
			throw exception(ID_CARD_FAILURE);
		}
		//2. 识别到图像存在风险,校验
		if (respDTO.getResult().getRisk() != 0) {
			log.error("OCR提示,图像存在风险");
			throw exception(OCR_IMAGE_RISK);
		}
		IdCardRespVO cardRespVO = BeanUtil.toBean(respDTO, IdCardRespVO.class);
		return new Result_IDCard(cardRespVO);
	}

	/**
	 * @param respVO  OCR识别结果
	 * @param plateNo OCR识别结果中的车牌号
	 * @param vin     OCR识别结果中的车架号
	 * @param owner   OCR识别结果中的车主姓名
	 */
	private record Result_VehicleLicense(VehicleLicenseRespVO respVO, String plateNo, String vin, String owner) {
		/*
		Java 14 引入的 record 类型声明
		代码简洁：1 行代码替代传统 50+ 行的 POJO 类
		不可变性：所有字段都是 final 的，线程安全
		值语义：自动实现的 equals/hashCode 方法适合基于值的比较
		模式匹配：为未来与 Java 模式匹配特性配合使用做好准备
		 */
	}

	private record Result_IDCard(IdCardRespVO idCardRespVO) {
	}

	@Override
	public CxProvinceDO getCxProvinceDO(String plateNo) {
		String plateNo_prefix = null;
		String firstChar = plateNo.substring(0, 1); // 提取首字符
		if (ArrayUtil.contains(InsureConstant.MUNICIPALITY_PLATE_NO_PREFIX, firstChar)) {
			plateNo_prefix = firstChar;
		} else {
			plateNo_prefix = plateNo.substring(0, 2);
		}

		CxProvinceDO cxProvinceDO = cxProvinceMapper.selectOne(new LambdaQueryWrapper<CxProvinceDO>()
			.eq(CxProvinceDO::getCarPlate, plateNo_prefix));
		if (cxProvinceDO == null) {
			log.error("根据车牌号前缀'{}'去查询数据表得到cxProvinceDO=null", plateNo_prefix);
			//车险出单配置-市与车险省市映射不存在
			throw exception(CX_PROVINCE_NOT_EXISTS);
		}
		return cxProvinceDO;
	}

	/**
	 * @param isPolicyQueryDetailResDTO 历史保单查询结果
	 * @param vin
	 * @param idNo
	 * @param vehicleLicenseRespVO      ORC原始结果的复制品
	 * @return
	 */
	private boolean processHisPolicyDetail(ISPolicyQueryDetailResDTO isPolicyQueryDetailResDTO, String vin, String idNo, VehicleLicenseRespVO vehicleLicenseRespVO) {
		boolean overwritten = false; // 新增标志位，记录是否覆写成功
		//保单标的信息
		List<ISMotorDTO> motorList = isPolicyQueryDetailResDTO.getMotorList();
		//保单关系人信息
		List<ISRelatedPartyDTO> relatedPartyList = isPolicyQueryDetailResDTO.getRelatedPartyList();

		// 将 motorList.forEach 替换为传统 for 循环，便于控制流程
		for (ISMotorDTO motor : motorList) {
			if (vin.equals(motor.getVinNo())) {
				if (idNo.equals(motor.getIdentifyNumber())) {
					// 覆写ORC识别的品牌型号（假设 motor 中有品牌型号字段，此处用 getModel() 示例）
					vehicleLicenseRespVO.getResult().getModel().setWords(motor.getBrandName());
					overwritten = true;
					break; // 找到匹配项，跳出循环
				} else {
					// 将 relatedPartyList.forEach 替换为传统 for 循环
					for (ISRelatedPartyDTO relatedParty : relatedPartyList) {
						if (idNo.equals(relatedParty.getIdentifyNumber())) {
							// 覆写ORC识别的品牌型号（假设从 motor 取品牌型号，根据实际业务调整）
							vehicleLicenseRespVO.getResult().getModel().setWords(motor.getBrandName());
							overwritten = true;
							break; // 找到匹配项，跳出关系人循环
						}
					}
					if (overwritten) {
						break; // 若关系人循环中已覆写，跳出motor循环
					}
				}
			}
		}
		return overwritten; // 返回是否覆写成功的结果
	}

	/**
	 * 请求第三方接口,报价平台-历史保单查询
	 *
	 * @param comCode  机构代码
	 * @param userCode 操作员工号
	 * @param plateNo  车牌
	 * @param vin vin
	 */
	@Nullable
	@Override
	public ISPolicyQueryDetailResDTO invokeQueryHisPolicyDetail(String comCode, String userCode, String plateNo,String vin) {
		//虚假数据  		plateNo = "赣C24242";

		//1. 构建请求头
		QueryHisPolicyDetailReqTotalDto queryHisPolicyDetailReqTotalDto = new QueryHisPolicyDetailReqTotalDto();
		CxRequestHeadDto cxRequestHeadDto = new CxRequestHeadDto();
		cxRequestHeadDto.setClientSeqNo(UUID.randomUUID().toString());
		cxRequestHeadDto.setComCode(comCode);
		cxRequestHeadDto.setUserCode(userCode);
		queryHisPolicyDetailReqTotalDto.setRequestHead(cxRequestHeadDto);
		//2. 构建请求体
		ISPolicyQueryMainRequest isPolicyQueryMainRequest = new ISPolicyQueryMainRequest();
		isPolicyQueryMainRequest.setLicenseNo(plateNo);
		if(vin !=null){
			isPolicyQueryMainRequest.setFrameNo(vin);
		}
		queryHisPolicyDetailReqTotalDto.setRequestBody(isPolicyQueryMainRequest);

		//3.调用API请求接口
		CommonResult<QueryHisPolicyDetailRespTotalDto> queryHisPolicyDetailRespTotalDtoCommonResult = null;

		try {
			queryHisPolicyDetailRespTotalDtoCommonResult = bjptApi.queryHisPolicyDetail(queryHisPolicyDetailReqTotalDto);
		} catch (Exception e) {
			log.error("bjptApi调用失败", e);
			throw exception(THIRD_PARTY_INTERFACE_CALL_FAILED);
		}
		if (queryHisPolicyDetailRespTotalDtoCommonResult == null
			|| queryHisPolicyDetailRespTotalDtoCommonResult.getCode() != 0
			|| queryHisPolicyDetailRespTotalDtoCommonResult.getData() == null
			|| (!ThirdConstant.BJPT_SUCCESS_FLAG.equals(queryHisPolicyDetailRespTotalDtoCommonResult.getData().getResponseHead().getResult())
			&& !ThirdConstant.BJPT_FAILURE_FLAG.equals(queryHisPolicyDetailRespTotalDtoCommonResult.getData().getResponseHead().getResult()))
		) {
			log.error("调用报价平台的历史保单查询接口失败,queryHisPolicyDetailRespTotalDtoCommonResult={}", queryHisPolicyDetailRespTotalDtoCommonResult);
			throw exception(THIRD_PARTY_INTERFACE_CALL_FAILED);
		}
		ISPolicyQueryDetailResDTO isPolicyQueryDetailResDTO = queryHisPolicyDetailRespTotalDtoCommonResult.getData().getResponseBody();
		return isPolicyQueryDetailResDTO;

	}

	/**
	 * OCR通用处理方法
	 *
	 * @param file  被ORC的文件
	 * @param reqVO
	 * @return
	 */
	@Override
	public OcrCommonRespVO ocrCommonHandle(MultipartFile file, OcrCommonReqVO reqVO) throws IOException {
		OcrCommonRespVO ocrCommonRespVO = switch (reqVO.getFileType()) {
			case VEHICLE_LICENSE -> {
				//ORC识别行驶证(正页)
				VehicleLicenseRespVO vehicleLicenseRespVO = ocrVehicleLicense(file, reqVO);
				//上传文件到S3,得到S3的存储绝对路径
				String uniqueFilename = uploadFileToS3(file, S3_DIR_VEHICLE_LICENSE);
				yield processResult(vehicleLicenseRespVO, uniqueFilename);

			}
			case ID_CARD -> {
				// OCR识别身份证正面
				IdCardRespVO idCardRespVO = ocrIDCard(file, reqVO);
				//上传文件到S3,得到S3的存储绝对路径
				String uniqueFilename = uploadFileToS3(file,S3_DIR_ID_CARD);
				yield processResult(idCardRespVO, uniqueFilename);
			}
			case ID_CARD_BACK -> {
				// OCR识别身份证背面
				IdCardRespVO idCardRespVO = ocrIDCardBack(file, reqVO);
				//上传文件到S3,得到S3的存储绝对路径
				String uniqueFilename = uploadFileToS3(file,S3_DIR_ID_CARD_BACK);
				yield processResult(idCardRespVO, uniqueFilename);
			}
			default -> throw exception(OCR_IMAGE_TYPE_ERROR);
		};

		return ocrCommonRespVO;
	}

	/**
	 * 身份证正面识别,并校验
	 *
	 * @param file
	 * @param reqVO
	 * @return
	 */
	private IdCardRespVO ocrIDCard(MultipartFile file, OcrCommonReqVO reqVO) throws IOException {
		//1.证件类型校验
		if(!reqVO.getIdType().equals("01")){
			log.error("只能OCR识别中国居民身份证");
			throw exception(OCR_IMAGE_TYPE_ERROR);
		}


		//2. OCR识别通用方法
		IdCardReqVO idCardReqVO = new IdCardReqVO();
		idCardReqVO.setImage_base64(Base64.getEncoder().encodeToString(file.getBytes()));
		IdCardRespVO idCardRespVO = getOcrResult_idCard(idCardReqVO).idCardRespVO();
		//3. 正面校验
		if (idCardRespVO.getResult().getFace() != 1) {
			log.error("OCR提示,非身份证正面");
			throw exception(NOT_ID_CARD_FRONT);
		}
		//4. 姓名校验
		if(reqVO.getRealName().equals(idCardRespVO.getResult().getName().getWords())){
			log.error("身份证姓名不匹配");
			throw exception(ID_CARD_NAME_MISMATCH);
		}
		//5. 证件号不匹配
		if(reqVO.getIdNo().equals(idCardRespVO.getResult().getIdno().getWords())){
			log.error("身份证号码不匹配");
			throw exception(ID_CARD_NUMBER_MISMATCH);
		}


		return idCardRespVO;

	}

	/**
	 * 身份证反面识别,并校验
	 *
	 * @param file
	 * @param reqVO
	 * @return
	 */
	private IdCardRespVO ocrIDCardBack(MultipartFile file, OcrCommonReqVO reqVO) throws IOException {
		//1. OCR识别通用方法
		IdCardReqVO idCardReqVO = new IdCardReqVO();
		idCardReqVO.setImage_base64(Base64.getEncoder().encodeToString(file.getBytes()));
		IdCardRespVO idCardRespVO = getOcrResult_idCard(idCardReqVO).idCardRespVO();
		//2. 正面校验
		if (idCardRespVO.getResult().getFace() != 2) {
			log.error("OCR提示,非身份证背面");
			throw exception(NOT_ID_CARD_BACK);
		}
		return idCardRespVO;
	}

	/**
	 * 根据第一个入参类型,构建OcrCommonRespVO对象返回
	 *
	 * @param vehicleLicenseRespVO
	 * @param uniqueFilename
	 * @return 重载
	 */
	private OcrCommonRespVO processResult(VehicleLicenseRespVO vehicleLicenseRespVO, String uniqueFilename) {
		return OcrCommonRespVO.builder().vehicleLicenseRespVO(vehicleLicenseRespVO).uniqueFilename(uniqueFilename).build();
	}

	/**
	 * 根据第一个入参类型,构建OcrCommonRespVO对象返回
	 *
	 * @param idCardRespVO
	 * @param uniqueFilename
	 * @return 重载
	 */
	private OcrCommonRespVO processResult(IdCardRespVO idCardRespVO, String uniqueFilename) {
		return OcrCommonRespVO.builder().idCardRespVO(idCardRespVO).uniqueFilename(uniqueFilename).build();
	}

	private String uploadFileToS3(MultipartFile file,String BizDir) {
		String uniqueFilename = fileUtil.getUniqueFilename(file, BizDir);
		try {
			PutObjectResult putObjectResult = amazonS3ObjectService.uploadMultipartFileToS3(s3Config.getBucketName(), uniqueFilename,
				file, Images_Water_Mark_Msg, IMAGES_WATER_MARK_COLOR_WHITE);
			return uniqueFilename;
		} catch (Exception e) {
			log.error("S3存储文件失败", e);
			throw exception(S3_FILE_STORAGE_FAILED);
		}

	}

	private VehicleLicenseRespVO ocrVehicleLicense(MultipartFile file, OcrCommonReqVO reqVO) throws IOException {
		//1. OCR识别行驶证正面,通用方法
		Result_VehicleLicense resultVehicleLicense = getOcrResult_vehicleLicense(
			new VehicleLicenseReqVO().setImage_base64(Base64.getEncoder().encodeToString(file.getBytes()))
				.setCarOwer(reqVO.getCarOwer())
				.setLicensePlateNumber(reqVO.getLicensePlateNumber())
				.setIdNo(reqVO.getIdNo())
		);
		//区别于	public VehicleLicenseRespVO vehicleLicense(@Valid VehicleLicenseReqVO reqVO)中的校验,因为需求文档中的返回文字不同了.这里单独处理
		//2.5 校验车主姓名
		if (!reqVO.getCarOwer().equals(resultVehicleLicense.owner())) {
			//当前车主姓名与上传行驶证信息不一致，请核对后重新填写或上传
			log.error("当前车主姓名与上传行驶证信息不一致，请核对后重新填写或上传,reqVO={},ORC识别结果中的车主姓名={}", reqVO, resultVehicleLicense.owner());
			throw exception(new ErrorCode(6_0127, "请上传车主《%s》的行驶证".formatted(reqVO.getCarOwer())));
		}
		//2.6 校验车牌号
		if (!reqVO.getLicensePlateNumber().equals(resultVehicleLicense.plateNo())) {
			//录入车牌号与行驶证不一致
			log.error("录入车牌号与行驶证不一致,reqVO={},ORC识别结果中的车牌号={}", reqVO, resultVehicleLicense.plateNo());
			throw exception(LICENSE_PLATE_MISMATCH);
		}
		return resultVehicleLicense.respVO();
	}
}